<script setup lang="ts">
import { onBeforeUnmount, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import html2canvas from 'html2canvas'
// import JSPDF from 'jspdf'
import JSZip from 'jszip'
import { saveAs } from 'file-saver'
import { merge } from 'lodash-es'
import type { ICaseTableItem } from '../type'
import ResultBrush from './result-brush.vue'
import { useCaseResult } from '@/views/cases/components/useCaseResult'
import usestore from '@/stores'
import { runCase, updateCase } from '@/api/cases'
import { useFetch } from '@/composables/useFetch'
import { b64toBlob } from '@/utils'

const { cases } = usestore()
const route = useRoute()

const caculationRef = ref()

// 页面请求
const { loading: runLoading, execute: runCaseExecute } = useFetch((parmas: any = {}) => runCase(parmas))
const { execute: updateCaseExecute } = useFetch((parmas: ICaseTableItem) => updateCase(parmas))
watch(() => runLoading.value, (val: boolean) => {
  cases.setCaseRunLoading(val)
})

// 点击运行前五步
async function onClickRunFiveStep() {
  console.log('onClickRunFiveStep cases.formInfo', cases.formInfo)

  cases.initFormInfoSkip()
  // 保存全量参数
  await updateCaseExecute({ caseId: route.query.id, jsonArgs: JSON.stringify(cases.formInfo) })

  // 运行操作
  await runCaseExecute({ caseId: route.query.id })
}

// function onClickExportResult() {
//   exportLoading.value = true
//   html2canvas(caculationRef.value, {}).then((canvas: any) => {
//     const dataStr = canvas.toDataURL()
//     const base64 = dataStr.replace(/^data:image\/\w+;base64,/, '')
//     downloadFile(base64, 'Caculation_Result', 'png')
//   }).finally(() => {
//     exportLoading.value = false
//   })
// }

const rawDataFigureRef = ref()
const brushRef = ref()
const twoDPCFigureRef = ref()
const threeDPCFigureRef = ref()
const exportLoading = ref(false)
async function onClickExportZip() {
  exportLoading.value = true

  // 这里添加异步的setTimeout会让exportLoading的变化快速显示到页面，不至于等到所有JS代码都执行完再渲染
  setTimeout(() => {
    Promise.all([
      getDomBase64(rawDataFigureRef.value),
      getDomBase64(brushRef.value),
      getDomBase64(twoDPCFigureRef.value),
      getDomBase64(threeDPCFigureRef.value),
    ]).then((res) => {
      const base64List = [
        {
          name: 'Raw Data Figure.png',
          data: res[0],
        },
        {
          name: 'Raw 2D PCs and 2D PCs figure.png',
          data: res[1],
        },
        {
          name: '2D PCs figure.png',
          data: res[2],
        },
        {
          name: '3D PCs figure.png',
          data: res[3],
        },
      ]

      // 创建一个 JSZip 实例
      const zip = new JSZip()

      // 遍历 base64 图片数组
      base64List.forEach((item) => {
        const blob = b64toBlob(item.data, 'image')

        // 将 Blob 对象添加到压缩包中
        zip.file(`${item.name}`, blob)
      })

      // 生成压缩包并触发下载
      zip.generateAsync({ type: 'blob' })
        .then((content: any) => {
          saveAs(content, 'Caculation Result.zip')
        })
    }).finally(() => {
      exportLoading.value = false
    })
  }, 500)
}

// 获取dom截图base64
async function getDomBase64(dom: any) {
  const canvas = await html2canvas(dom, {
    scale: window.devicePixelRatio * 2,
  })
  const dataStr = canvas.toDataURL()
  const base64 = dataStr.replace(/^data:image\/\w+;base64,/, '')
  return base64
}

const {
  onClickRefreshAllAction,
  onClickToggleAllLine,
  dRClsusterLoading,
  rawLoading,
  sampleLoading,
  tableColumns,
  tableData,
  sampleDataResult,
  lineOptions,
  hasLineData,
  scatter2DOptions,
  scatter2DSelectOptions,
  scatter2DXAxisValue,
  scatter2DYAxisValue,
  scatter3DOptions,
  scatter3DSelectOptions,
  scatter3DXAxisValue,
  scatter3DYAxisValue,
  scatter3DZAxisValue,
} = useCaseResult()

scatter3DOptions.value = _handle3DCategoryPostion(scatter3DOptions.value)

function _handle3DCategoryPostion(threeDOptions: any) {
  return merge(
    {},
    threeDOptions,
    {
      visualMap: {
        left: 'center',
        top: 10,
        orient: 'horizontal',
      },
    },
  )
}

onBeforeUnmount(() => {
  tableData.value = tableColumns.value = null as any
  lineOptions.value = hasLineData.value = null as any
  sampleDataResult.value = null as any
  scatter2DOptions.value = scatter2DSelectOptions.value = scatter2DXAxisValue.value = scatter2DYAxisValue.value = null as any
  scatter3DOptions.value = scatter3DSelectOptions.value = scatter3DXAxisValue.value = scatter3DYAxisValue.value = scatter3DZAxisValue.value = null as any
})

defineExpose({ onClickRunFiveStep, onClickRefreshAllAction })
</script>

<template>
  <div ref="caculationRef" class="case-result-wrapper gp__flex-between">
    <div class="box">
      <div class="header title">
        <span class="name">Caculation Result</span>
        <div>
          <!-- <a-button style="margin-right: 10px" type="primary" class="ant-max-btn" :disabled="exportLoading" @click="onClickExportResult">
            Report
          </a-button> -->
          <a-button type="primary" class="ant-max-btn" :disabled="exportLoading" @click="onClickExportZip">
            {{ exportLoading ? 'Reporting' : 'Report' }}
          </a-button>
        </div>
      </div>
      <div class="content" style="padding: 10px">
        <div>
          <div class="box">
            <div class="header">
              <span class="name">Raw Table</span>
            </div>
            <div class="content">
              <a-table :columns="tableColumns" :loading="rawLoading" :data-source="tableData" :scroll="{ x: 1080 }" size="middle" />
            </div>
          </div>
          <div ref="rawDataFigureRef" class="box">
            <div class="header">
              Raw Data Figure
            </div>
            <div class="content">
              <div v-if="hasLineData" class="toggle-all-line" @click="onClickToggleAllLine">
                <span class="toggle">ALL</span>
              </div>
              <a-spin tip="loading..." :spinning="rawLoading">
                <GpChart id="caseLine" :options="lineOptions" height="450px" width="100%" style="border: 1px solid; margin: 20px auto" />
              </a-spin>
            </div>
          </div>
        </div>
        <div>
          <div ref="brushRef" class="box">
            <div class="header">
              Raw 2D PCs and 2D PCs figure
            </div>
            <div class="content">
              <ResultBrush :case-result="sampleDataResult" :loading="sampleLoading" />
            </div>
          </div>
          <div ref="twoDPCFigureRef" class="box">
            <div class="header">
              2D PCs figure
            </div>
            <div class="content">
              <div class="select-wrapper">
                <div class="row">
                  <span>xAxis2D:</span>
                  <a-select
                    v-model:value="scatter2DXAxisValue"
                    style="width: 100%"
                    size="small"
                    :options="scatter2DSelectOptions"
                  />
                </div>
                <div class="row">
                  <span>yAxis2D:</span>
                  <a-select
                    v-model:value="scatter2DYAxisValue"
                    style="width: 100%"
                    size="small"
                    :options="scatter2DSelectOptions"
                  />
                </div>
              </div>
              <a-spin tip="loading..." :spinning="dRClsusterLoading">
                <GpChart id="case2DScatter" :options="scatter2DOptions" width="60%" style="border: 1px solid; margin: 20px auto" />
              </a-spin>
            </div>
          </div>
          <div ref="threeDPCFigureRef" class="box" style="padding-bottom: 10px;">
            <div class="header">
              3D PCs figure
            </div>
            <div class="content">
              <div class="select-wrapper">
                <div class="row">
                  <span>xAxis3D:</span>
                  <a-select
                    v-model:value="scatter3DXAxisValue"
                    style="width: 100%"
                    size="small"
                    :options="scatter3DSelectOptions"
                  />
                </div>
                <div class="row">
                  <span>yAxis3D:</span>
                  <a-select
                    v-model:value="scatter3DYAxisValue"
                    style="width: 100%"
                    size="small"
                    :options="scatter3DSelectOptions"
                  />
                </div>
                <div class="row">
                  <span>zAxis3D:</span>
                  <a-select
                    v-model:value="scatter3DZAxisValue"
                    style="width: 100%"
                    size="small"
                    :options="scatter3DSelectOptions"
                  />
                </div>
              </div>
              <a-spin tip="loading..." :spinning="dRClsusterLoading">
                <GpChart id="case3DScatter" :options="scatter3DOptions" width="60%" style="border: 1px solid; margin: 20px auto" />
              </a-spin>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
@import url('../common.less');
.case-result-wrapper .content {
  position: relative;
  .toggle-all-line {
    display: inline-block;
    position: absolute;
    left: calc(50% - 50px);
    top: -10px;
    font-size: 14px;
    z-index: 9999;
    .toggle {
      color: #fff;
      padding: 2px 10px;
      border-radius: 4px;
      background-color: @color-theme;
      cursor: pointer;
    }
  }
}
</style>
